import {
	DB,
	lumpSumCarFareLibraryKey,
	travelAddressLibraryKey,
	travelPeopleLibraryKey,
	travelRecordLibraryKey,
} from "@/assets/global"
import { showFailToast, showSuccessToast, UploaderAfterRead } from "vant"
import { TravelPerson, TTravelInfo } from "../AddTravelRecord/AddTravelRecord"
import * as indexedDB from "@utility/indexedDB"
import TravelRecordLibraryStore from "@/store/TravelRecordLibraryStore"
const store = TravelRecordLibraryStore()

const importDataUtil: UploaderAfterRead = async file => {
	try {
		if (Array.isArray(file)) {
			console.warn("不支持多文件上传")
			return
		}

		const text = await extractFileContent(file)
		await processImportedData(text)
	} catch (error) {
		handleImportError(error)
	}
}

// 辅助函数：提取文件内容（保持不变）
async function extractFileContent(file: any): Promise<string> {
	if (file instanceof File || file instanceof Blob) {
		return await readFileAsText(file)
	}

	if (typeof file === "object" && file.content?.startsWith("data:")) {
		return decodeBase64Content(file.content)
	}

	throw new Error("不支持的文件格式")
}

// 辅助函数：处理导入的数据（支持0-4个字段）
async function processImportedData(text: string) {
	const handleData = JSON.parse(text)

	// 定义可能的库字段及其处理方式
	const libraryProcessors = {
		[travelRecordLibraryKey]: {
			process: async (data: any) => {
				const travelRecord = importTravelInfos(JSON.stringify(data))
				await indexedDB.batchAdd(DB.store.TravelRecord.name, travelRecord)
			},
			required: false,
		},
		[travelPeopleLibraryKey]: {
			process: (data: any) => {
				store.PeopleLibrary = data
			},
			required: false,
		},
		[travelAddressLibraryKey]: {
			process: (data: any) => {
				store.AddressLibrary = data
			},
			required: false,
		},
		[lumpSumCarFareLibraryKey]: {
			process: (data: any) => {
				store.LumpSumCarFareLibrary = data
			},
			required: false,
		},
	}

	// 统计成功导入的库数量
	let successCount = 0
	const importResults: string[] = []

	// 处理每个可能的库
	for (const [key, processor] of Object.entries(libraryProcessors)) {
		if (key in handleData) {
			try {
				await processor.process(handleData[key])
				successCount++
				importResults.push(`${key}\n导入成功`)
			} catch (error) {
				importResults.push(`${key}\n导入失败: ${(error as Error).message}`)
			}
		} else if (processor.required) {
			importResults.push(`${key} 缺失（必需字段）`)
		}
	}

	// 根据导入结果显示反馈
	if (successCount > 0) {
		showSuccessToast({
			message: `成功导入 ${successCount} 个记录库\n${importResults.join("\n")}`,
			duration: 6000,
		})
	} else {
		throw new Error("没有成功导入任何记录库\n" + importResults.join("\n"))
	}
}

// 辅助函数：处理错误（保持不变）
function handleImportError(error: unknown) {
	console.error("导入失败:", error)

	const errorMessage = error instanceof Error ? error.message : String(error)

	showFailToast({
		message: `导入失败\n${errorMessage}`,
		duration: 4000,
	})
}

// -------------------- 工具函数 --------------------
/**
 * 读取 File/Blob 为文本（浏览器标准 API）
 */
const readFileAsText = (file: File | Blob): Promise<string> => {
	return new Promise((resolve, reject) => {
		const reader = new FileReader()
		reader.onload = e => resolve(e.target?.result as string)
		reader.onerror = () => reject(new Error("文件读取失败"))
		reader.readAsText(file, "UTF-8") // 显式指定 UTF-8 编码
	})
}

/**
 * 解码 Base64 Data URL 内容（兼容移动端和浏览器）
 */
const decodeBase64Content = (dataUrl: string): string => {
	const base64 = dataUrl.split(",")[1]

	// 方案1：优先用 Buffer（Node.js 和现代浏览器）
	if (typeof Buffer !== "undefined") {
		return Buffer.from(base64, "base64").toString("utf-8")
	}

	// 方案2：降级到 TextDecoder + atob
	if (typeof TextDecoder !== "undefined") {
		const binaryString = atob(base64)
		const bytes = new Uint8Array(binaryString.length)
		for (let i = 0; i < binaryString.length; i++) {
			bytes[i] = binaryString.charCodeAt(i)
		}
		return new TextDecoder("utf-8").decode(bytes)
	}

	// 方案3：终极降级方案（旧浏览器）
	return decodeURIComponent(escape(atob(base64)))
}

export const importTravelInfos = (data: string) => {
	// 解析 JSON 字符串为 TravelInfo[]
	const parseDatas = JSON.parse(data) as Array<
		{
			// 这里只列出需要转换的属性，其他属性可以省略，因为 TypeScript 会从 TravelInfo 接口中推断它们
			travelPeople: TravelPerson[]
		} & Omit<TTravelInfo, "travelPeople">
	>

	// 映射数组，转换 travelPeople 属性为 Set
	return parseDatas.map(item => ({
		// 使用 Omit 排除 travelPeople 属性，然后将其与其他属性合并
		...(item as Omit<TTravelInfo, "travelPeople">),
		travelPeople: Array.from(item.travelPeople),
	}))
}

export default importDataUtil
